/* 
 * File:   netcdfWrite.cpp
 * Author: gian
 * 
 * Created on April 27, 2012, 12:49 PM
 */

#include <string>
#include <sstream>
#include <iomanip>
#include "netcdfWrite.hpp"


netcdf_os_complex_float::netcdf_os_complex_float(const char* filename, const char* channelname, int framesize)
:
mFilename(filename),mChannelname(channelname)
{
    mFrameSize = framesize;
    mRecord = 0;
    mDataPtr = 0;
    mDt = 1.0;
    mDataRe = new float[mFrameSize];
    mDataIm = new float[mFrameSize];
    mRecordCheckpointSize = -1;
    mCheckpointCount = 0;
    mFile = 0;
}


void netcdf_os_complex_float::OpenFile()
{
    std::ostringstream fname;
    fname << mFilename << std::setfill('0') << std::setw(6) << mCheckpointCount << ".ncdf";
    mFile = new NcFile(fname.str().c_str(),NcFile::Replace,NULL,0,NcFile::Offset64Bits);
    mFile->add_dim("t",mFrameSize);
    mFile->add_dim("time",NC_UNLIMITED);    
    mFile->add_var("time",ncDouble,mFile->get_dim(1));
    std::string cre = mChannelname + std::string(".re");
    std::string cim = mChannelname + std::string(".im");
    NcVar* var=mFile->add_var(cre.c_str(),ncFloat,mFile->get_dim(1),mFile->get_dim(0)); 
    var->add_att("sampling_rate",mDt);
    var = mFile->add_var(cim.c_str(),ncFloat,mFile->get_dim(1),mFile->get_dim(0)); 
    var->add_att("sampling_rate",mDt);
}

netcdf_os_complex_float::~netcdf_os_complex_float()
{
    for(mDataPtr++;mDataPtr<mFrameSize;mDataPtr++) {
        mDataRe[mDataPtr] = mDataIm[mDataPtr] = 0.0;
    }
    DataFlush();
    delete[] mDataRe;
    delete[] mDataIm;
    delete mFile;
}
    
void netcdf_os_complex_float::set_rate(double dt)
{
    mDt = dt;
}

void netcdf_os_complex_float::write(cvectorf* data)
{
    if(mFile==0) OpenFile();
    gsl_complex_float val;
    for(int i=0;i<data->v->size;i++) {
        val = data->get(i);
        mDataRe[mDataPtr] = val.dat[0];
        mDataIm[mDataPtr] = val.dat[1];
        mDataPtr++;
        if(mDataPtr==mFrameSize) DataFlush();
    }
}

void netcdf_os_complex_float::write(vectorf* redata, vectorf* imdata)
{
    if(redata->size() != imdata->size()) {
        std::cerr << "Size of input vectors are different" << std::endl;
        throw;
    }
    if(mFile==0) OpenFile();
    for(int i=0;i<redata->size();i++) {
        mDataRe[mDataPtr] = redata->get(i);
        mDataIm[mDataPtr] = imdata->get(i);
        mDataPtr++;
        if(mDataPtr==mFrameSize) DataFlush();
    }
}


void netcdf_os_complex_float::DataFlush()
{
    double time;
    if(mRecordCheckpointSize<1) {
        time = mDt*mFrameSize*mRecord;
    } else {
        time = mDt*mFrameSize*(mRecord+mRecordCheckpointSize*mCheckpointCount);
    }
    
    mFile->get_var(0)->put_rec(&time,mRecord);
    mFile->get_var(1)->put_rec(mDataRe,mRecord);
    mFile->get_var(2)->put_rec(mDataIm,mRecord);
    mRecord++;
    mDataPtr = 0;
    if( mRecord == mRecordCheckpointSize ) {
        DataCheckpoint();
        mRecord = 0;
    } 
}

void netcdf_os_complex_float::DataCheckpoint()
{
    mFile->close();
    delete mFile;
    mCheckpointCount++;
    OpenFile();
}

void netcdf_os_complex_float::set_checkpoint_size(int numframes)
{
    mRecordCheckpointSize = numframes;
}

netcdf_os_double::netcdf_os_double(const char* filename, const char* channelname, int framesize)
:
mFilename(filename),mChannelname(channelname)
{
    mFrameSize = framesize;
    mRecord = 0;
    mDataPtr = 0;
    mDt = 1.0;
    mData = new double[mFrameSize];
    mRecordCheckpointSize = -1;
    mCheckpointCount = 0;
    mFile = 0; 
}


void netcdf_os_double::OpenFile()
{
    std::ostringstream fname;
    fname << mFilename << std::setfill('0') << std::setw(6) << mCheckpointCount << ".ncdf";
    mFile = new NcFile(fname.str().c_str(),NcFile::Replace,NULL,0,NcFile::Offset64Bits);
    mFile->add_dim("t",mFrameSize);
    mFile->add_dim("time",NC_UNLIMITED);    
    mFile->add_var("time",ncDouble,mFile->get_dim(1));
    NcVar* var = mFile->add_var(mChannelname.c_str(),ncDouble,mFile->get_dim(1),mFile->get_dim(0)); 
    var->add_att("sampling_rate",mDt);
 }

netcdf_os_double::~netcdf_os_double()
{
    for(mDataPtr++;mDataPtr<mFrameSize;mDataPtr++) {
        mData[mDataPtr] = 0.0;
    }
    DataFlush();
    delete[] mData;
    delete mFile;
}
    
void netcdf_os_double::set_rate(double dt)
{
    mDt = dt;
}

void netcdf_os_double::write(vector* data)
{
    if(mFile==0) OpenFile();
    double val;
    for(int i=0;i<data->v->size;i++) {
        val = data->get(i);
        mData[mDataPtr] = val;
        mDataPtr++;
        if(mDataPtr==mFrameSize) DataFlush();
    }
}

void netcdf_os_double::DataFlush()
{
    double time;
    if(mRecordCheckpointSize<1) {
        time = mDt*mFrameSize*mRecord;
    } else {
        time = mDt*mFrameSize*(mRecord+mRecordCheckpointSize*mCheckpointCount);
    }
    
    mFile->get_var(0)->put_rec(&time,mRecord);
    mFile->get_var(1)->put_rec(mData,mRecord);
    mRecord++;
    mDataPtr = 0;
    if( mRecord == mRecordCheckpointSize ) {
        DataCheckpoint();
        mRecord = 0;
    } 
}

void netcdf_os_double::DataCheckpoint()
{
    mFile->close();
    delete mFile;
    mCheckpointCount++;
    OpenFile();
}

void netcdf_os_double::set_checkpoint_size(int numframes)
{
    mRecordCheckpointSize = numframes;
}




netcdf_os_float::netcdf_os_float(const char* filename, const char* channelname, int framesize)
:
mFilename(filename),mChannelname(channelname)
{
    mFrameSize = framesize;
    mRecord = 0;
    mDataPtr = 0;
    mDt = 1.0;
    mData = new float[mFrameSize];
    mRecordCheckpointSize = -1;
    mCheckpointCount = 0;
    mFile = 0; 
}


void netcdf_os_float::OpenFile()
{
    std::ostringstream fname;
    fname << mFilename << std::setfill('0') << std::setw(6) << mCheckpointCount << ".ncdf";
    mFile = new NcFile(fname.str().c_str(),NcFile::Replace,NULL,0,NcFile::Offset64Bits);
    mFile->add_dim("t",mFrameSize);
    mFile->add_dim("time",NC_UNLIMITED);    
    mFile->add_var("time",ncDouble,mFile->get_dim(1));
    NcVar* var = mFile->add_var(mChannelname.c_str(),ncFloat,mFile->get_dim(1),mFile->get_dim(0)); 
    var->add_att("sampling_rate",mDt);
 }

netcdf_os_float::~netcdf_os_float()
{
    for(mDataPtr++;mDataPtr<mFrameSize;mDataPtr++) {
        mData[mDataPtr] = 0.0;
    }
    DataFlush();
    delete[] mData;
    delete mFile;
}
    
void netcdf_os_float::set_rate(double dt)
{
    mDt = dt;
}

void netcdf_os_float::write(vectorf* data)
{
    if(mFile==0) OpenFile();
    float val;
    for(int i=0;i<data->v->size;i++) {
        val = data->get(i);
        mData[mDataPtr] = val;
        mDataPtr++;
        if(mDataPtr==mFrameSize) DataFlush();
    }
}

void netcdf_os_float::DataFlush()
{
    double time;
    if(mRecordCheckpointSize<1) {
        time = mDt*mFrameSize*mRecord;
    } else {
        time = mDt*mFrameSize*(mRecord+mRecordCheckpointSize*mCheckpointCount);
    }
    
    mFile->get_var(0)->put_rec(&time,mRecord);
    mFile->get_var(1)->put_rec(mData,mRecord);
    mRecord++;
    mDataPtr = 0;
    if( mRecord == mRecordCheckpointSize ) {
        DataCheckpoint();
        mRecord = 0;
    } 
}

void netcdf_os_float::DataCheckpoint()
{
    mFile->close();
    delete mFile;
    mCheckpointCount++;
    OpenFile();
}

void netcdf_os_float::set_checkpoint_size(int numframes)
{
    mRecordCheckpointSize = numframes;
}





